home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1993 / MacHack 1993.toast / MacHack™ 1987-1992 / MacHack™ '90 / Source Code ƒ / MPW C ƒ / TRUCHTƒ / tile.c next >
Encoding:
C/C++ Source or Header  |  1990-06-14  |  5.7 KB  |  307 lines  |  [TEXT/MPS ]

  1. /*
  2.     Truchet Tiling - by John Jeppson.
  3.     
  4.     This source code is in the public domain.
  5.     Written in MPW C.
  6.     
  7.     This program is an MPW Tool which implements Truchet Tiling
  8.     as described in "Computer Recreations" by A.K.Dewdney in 
  9.     Scientific American, July 1989.
  10.     
  11.     From the MPW Worksheet execute:
  12.     
  13.             Tile n
  14.             
  15.     where "n" is an integer [0..100] which represents the percentage
  16.     bias for an otherwise random test array, as described in the
  17.     same article.  A value of 0 yields a completely random array.
  18.     
  19.     After the tiling is drawn you will hear a SysBeep.
  20.     You may print the completed tiling by pressing "p".
  21.     Return to the shell with the close box.
  22. */
  23.  
  24. #include <Types.h>
  25. #include <Windows.h>
  26. #include <Memory.h>
  27. #include <Printing.h>
  28. #include <Fonts.h>
  29. #include <Resources.h>
  30. #include <OSUtils.h>
  31.  
  32. #define TruchetRadius    5        /* radius of tiling curves */
  33.  
  34. #define windowTop        40
  35. #define windowLeft        4
  36. #define windowHeight    250
  37. #define windowWidth        400
  38. #define windowTitle        "\pTruchet Tiling"
  39.  
  40. #define maxX            ( windowWidth  / (TruchetRadius * 2) + 1 )
  41. #define maxY            ( windowHeight / (TruchetRadius * 2) + 1 )
  42.  
  43. #define nil                0L
  44.  
  45.  
  46. /**** globals ****/
  47.  
  48.     long        bias;
  49.     Boolean        array[maxX][maxY];
  50.     WindowPtr    display;
  51.     Boolean        alreadyDrawn;
  52.     BitMap        offScreen;
  53.  
  54.  
  55. /**** the tiling procedures ****/
  56.  
  57. void TruchetA(short x, short y, short radius)
  58. {
  59.     Rect r;
  60.     
  61.     SetRect(&r, x - radius, y - radius, x + radius, y + radius);
  62.     FrameArc(&r, 90, 90);
  63.     OffsetRect(&r, radius * 2, radius * 2);
  64.     FrameArc(&r, 270, 90);
  65. }
  66.  
  67. void TruchetB(short x, short y, short radius)
  68. {
  69.     Rect r;
  70.     
  71.     SetRect(&r, x + radius, y - radius, x + (radius * 3), y + radius);
  72.     FrameArc(&r, 180, 90);
  73.     OffsetRect(&r, - (radius * 2), radius * 2);
  74.     FrameArc(&r, 0, 90);
  75. }
  76.  
  77. void TruchetTile(
  78.     short        rows,
  79.     short        cols,
  80.     short        radius,                            /* radius of Truchet tiling curves */
  81.     Boolean        (*fetch)(short x, short y) )    /* called to get orientation */
  82. {
  83.     short    i,j;
  84.     
  85.     PenNormal();
  86.     for ( i = 0; i < cols; ++i )
  87.         for ( j = 0; j < rows; ++j )
  88.             if ( (*fetch)(i,j) )
  89.                 TruchetA(i * radius * 2, j * radius * 2, radius);
  90.             else
  91.                 TruchetB(i * radius * 2, j * radius * 2, radius);
  92. }
  93.  
  94.  
  95.  
  96. /**** data manipulation for this example ****/
  97.  
  98.  
  99. Boolean    getValue(short x, short y)
  100. {
  101.     return array[x][y];
  102. }
  103.  
  104.  
  105. void initArray()
  106. {
  107.     short        i, j, n;
  108.     Boolean        carry;
  109.     
  110.     for ( j = 0; j < maxY; ++j )
  111.     {
  112.         carry = false;
  113.         for ( i = 0; i < maxX; ++i )
  114.         {
  115.             n = Random() % 100;
  116.             if ( n >= bias )
  117.                 carry = ((n % 2) == 0);
  118.             array[i][j] = carry;
  119.         }
  120.     }
  121. }
  122.  
  123.  
  124. void drawContents(WindowPtr w)
  125. {
  126.     EraseRect(&(w->portRect));
  127.     
  128.     if ( alreadyDrawn )
  129.     {
  130.         CopyBits (&offScreen, &(display->portBits),
  131.                     &(offScreen.bounds), &(offScreen.bounds),
  132.                         srcCopy, nil);
  133.     }
  134.     else
  135.     {
  136.         TruchetTile (maxY, maxX, TruchetRadius, getValue);
  137.         alreadyDrawn = true;
  138.         CopyBits (&(display->portBits), &offScreen,
  139.                     &(offScreen.bounds), &(offScreen.bounds),
  140.                         srcCopy, nil);
  141.         SysBeep(1);
  142.     }
  143. }
  144.  
  145.  
  146. /**** generic tool stuff ****/
  147.  
  148.  
  149. void doUpdate(WindowPtr w)
  150. {
  151.     GrafPtr    savePort;
  152.     
  153.     GetPort(&savePort);
  154.     SetPort(w);
  155.     ClipRect(&(w->portRect));
  156.     BeginUpdate(w);
  157.         drawContents(w);
  158.     EndUpdate(w);
  159.     SetPort(savePort);
  160. }
  161.  
  162.  
  163. void makeOffScreen()   /* set up offscreen bitmap to store image */
  164. {
  165.     Size        sizeOfOff;
  166.     short        offRowBytes;
  167.  
  168.     offRowBytes = (((windowWidth - 1) / 16) + 1) * 2;
  169.     sizeOfOff = windowHeight * offRowBytes;
  170.     
  171.     offScreen.baseAddr = (QDPtr) NewPtr(sizeOfOff);
  172.     offScreen.rowBytes = offRowBytes;
  173.     SetRect(&(offScreen.bounds), 0, 0, windowWidth, windowHeight);
  174. }
  175.  
  176.  
  177. void makeWindow()
  178. {
  179.     Rect    bounds;
  180.  
  181.     SetRect(&bounds, windowLeft, windowTop, windowLeft + windowWidth, windowTop + windowHeight);
  182.     display = NewWindow(nil, &bounds, windowTitle, true, noGrowDocProc, (WindowPtr) -1, true, 0L);
  183. }
  184.  
  185.  
  186. void printTile()
  187. {
  188.     TPPrPort    pport;
  189.     THPrint        hPrint;
  190.     TPrStatus    PrStatus;
  191.     GrafPtr        oldPort;  
  192.     Boolean     notCancelled = true;
  193.     Boolean        drop;
  194.  
  195.     GetPort (&oldPort);
  196.     PrOpen();
  197.  
  198.     SetFractEnable(true);
  199.     SetFScaleDisable(true);
  200.  
  201.     hPrint = (THPrint) NewHandle(sizeof(TPrint));
  202.     if (ResError())
  203.     {
  204.         printf ("Printing Error %d\n", ResError());
  205.         SysBeep(1);
  206.         PrClose();
  207.         return;
  208.     }
  209.     
  210.     drop = PrValidate(hPrint);
  211.     notCancelled = PrJobDialog (hPrint);
  212.         
  213.     if (notCancelled)
  214.     {
  215.         pport = PrOpenDoc(hPrint, nil, nil);
  216.         if ( PrError() == noErr )
  217.         {
  218.             PrOpenPage(pport, nil);
  219.             if (PrError()==noErr)
  220.                 CopyBits (&offScreen, &(pport->gPort.portBits),
  221.                     &(offScreen.bounds), &(offScreen.bounds),
  222.                         srcCopy, nil);
  223.             PrClosePage(pport);
  224.         }
  225.         PrCloseDoc(pport);
  226.     }
  227.     if ( ((**hPrint).prJob.bJDocLoop == bSpoolLoop)
  228.              && (PrError() == noErr) )
  229.         PrPicFile (hPrint, nil, nil, nil, &PrStatus);
  230.         
  231.     SetFractEnable(false);
  232.     SetFScaleDisable(false);
  233.  
  234.     PrClose();
  235.  
  236.     SetPort (oldPort);
  237. }
  238.  
  239. void mainLoop()
  240. {
  241.     Boolean            done = false;
  242.     EventRecord        theEvent;
  243.     WindowPtr        whichWindow;
  244.     short            part;
  245.     
  246.     while ( !done )
  247.     {
  248.         if ( GetNextEvent(everyEvent, &theEvent) )
  249.         {
  250.             switch ( theEvent.what )
  251.             {
  252.                 case updateEvt:
  253.                     doUpdate(display);
  254.                     break;
  255.  
  256.                 case mouseDown:
  257.                     part = FindWindow(theEvent.where, &whichWindow);
  258.                     if ( (whichWindow == display) && (part == inGoAway) )
  259.                         done = true;
  260.                     break;
  261.  
  262.                 case keyDown:
  263.                     if ( 'p' == (theEvent.message & charCodeMask) )
  264.                         printTile();
  265.                     break;
  266.             }
  267.         }
  268.     }
  269. }
  270.  
  271.  
  272. void cleanUp()
  273. {
  274.     DisposeWindow(display);
  275.     DisposPtr((Ptr) offScreen.baseAddr);
  276. }
  277.  
  278.  
  279. int main (
  280.     int  argc,            /* number of arguments */
  281.     char *argv[],        /* pointer to array of argument strings */
  282.     char *envp[])        /* pointer to array of variable definitions */
  283. {
  284.     #pragma unused (envp)
  285.  
  286.     InitGraf((Ptr) &qd.thePort);
  287.     SetFScaleDisable(true);
  288.     InitCursor();
  289.     
  290.     if ( argc != 2 )
  291.     {
  292.         printf ("### Wrong Number of Parameters ###\n");
  293.         return 2;
  294.     }
  295.     bias = atol(argv[1]);
  296.  
  297.     alreadyDrawn = false;
  298.     
  299.     makeOffScreen();
  300.     initArray();
  301.     makeWindow();
  302.     mainLoop();
  303.     cleanUp();
  304.  
  305.     return 0;
  306. }
  307.